/*
**********************************************************************
*                          Micrium, Inc.
*                      949 Crestview Circle
*                     Weston,  FL 33327-1848
*
*                            uC/FS
*
*             (c) Copyright 2001 - 2003, Micrium, Inc.
*                      All rights reserved.
*
***********************************************************************

----------------------------------------------------------------------
File        : fat_in.c
Purpose     : FAT read routines
----------------------------------------------------------------------
Known problems or limitations with current version
----------------------------------------------------------------------
None.
---------------------------END-OF-HEADER------------------------------
*/

/*********************************************************************
*
*             #include Section
*
**********************************************************************
*/

#include "fs_conf.h"
#include "fs_port.h"
#include "fs_dev.h"
#include "fs_api.h"
#include "fs_fsl.h"
#include "fs_int.h"
#include "fs_os.h"
#include "fs_lbl.h"
#include "fs_fat.h"


/*********************************************************************
*
*             Global functions
*
**********************************************************************
*/

/*********************************************************************
*
*             FS__fat_fread
*
  Description:
  FS internal function. Read data from a file.

  Parameters:
  pData       - Pointer to a data buffer for storing data transferred
                from file. 
  Size        - Size of an element to be transferred from file to data
                buffer
  N           - Number of elements to be transferred from the file.
  pFile       - Pointer to a FS_FILE data structure.
  
  Return value:
  Number of elements read.
*/
#if 1
FS_size_t FS__fat_fread(void *pData, FS_size_t Size, FS_size_t N, FS_FILE *pFile) {
  FS_size_t todo;
  FS_u32 i;
  FS_u32 j;
  FS_u32 fatsize;
  FS_u32 fileclustnum;
  FS_u32 diskclustnum;
  FS_u32 prevclust;
  FS_u32 dstart;
  FS_u32 dsize;
  FS_u32 datastart;
  char *buffer;
  int err;
                                            
  if (!pFile) {
      return 0;  /* No valid pointer to a FS_FILE structure */
  }
  /* Check if media is OK */
  err = FS__lb_status(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo);
  if (err == FS_LBL_MEDIACHANGED) {
    /* Media has changed */
    pFile->error = FS_ERR_DISKCHANGED;
    return 0;
  }
  else if (err < 0) {
    /* Media cannot be accessed */
    pFile->error = FS_ERR_READERROR;
    return 0;
  }
  buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  if (!buffer) {
    return 0;
  }
  fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz16;
  if (fatsize == 0) {
    /* FAT32 */
     fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz32;
  }
  dstart    = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RsvdSecCnt + FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].NumFATs * fatsize;
  dsize     = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RootEntCnt) * FS_FAT_DENTRY_SIZE) / FS_FAT_SEC_SIZE;
  datastart = dstart + dsize;
  prevclust = 0;
  todo = N * Size;
  while (todo) 
  {
	  if (pFile->filepos >= pFile->size) {
		  /* EOF has been reached */
		  pFile->error = FS_ERR_EOF;
		  FS__fat_free(buffer);
		  return ((N * Size - todo) / Size);
	  }
	  fileclustnum = pFile->filepos / (FS_FAT_SEC_SIZE * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus);
	  if (prevclust == 0) {
		  diskclustnum = pFile->CurClust; 
		  if (diskclustnum == 0) {
			  /* Find current cluster by starting at 1st cluster of the file */
			  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pFile->fileid_hi, fileclustnum);
		  }
	  }
	  else {
		  /* Get next cluster of the file */
		  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, prevclust, 1);
	  }
	  prevclust       = diskclustnum;
	  pFile->CurClust = diskclustnum;
	  if (diskclustnum == 0) {
		  /* Could not find current cluster */
		  pFile->error = FS_ERR_READERROR;
		  FS__fat_free(buffer);
		  return ((N * Size - todo) / Size);
	  }
	  diskclustnum -= 2;
	  j = (pFile->filepos % (FS_FAT_SEC_SIZE * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus))/ FS_FAT_SEC_SIZE;
		
	  while (1) 
	  {
		  if (!todo) {
			  break;  /* Nothing more to write */
		  }
		  if (j >= (FS_u32)FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus) {
			  break;  /* End of the cluster reached */
		  }
		  if (pFile->filepos >= pFile->size) {
			  break;  /* End of the file reached */
		  }
		  err = FS__lb_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
				    datastart +
				    diskclustnum * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus + j,
				    (void*)buffer);
		  if (err < 0) {
			  pFile->error = FS_ERR_READERROR;
			  FS__fat_free(buffer);
			  return ((N * Size - todo) / Size);
		  }
		  i = pFile->filepos % FS_FAT_SEC_SIZE;
		  if(FS_FAT_SEC_SIZE-i > todo)
		  {
		  	FS__CLIB_memcpy((char *)((unsigned int)pData + N * Size - todo), &buffer[i],todo);
			  pFile->filepos += todo;
			  todo = 0;
			  i += todo;
		  }
		  else
		  {
		  	FS__CLIB_memcpy((char *)((unsigned int)pData +  N * Size - todo), &buffer[i],FS_FAT_SEC_SIZE-i);
			  pFile->filepos += (FS_FAT_SEC_SIZE-i);
			  todo -= (FS_FAT_SEC_SIZE-i);
			  i = FS_FAT_SEC_SIZE;
		  }

		  j++;
	  }  /* Sector loop */
  }  /* Cluster loop */
  if (i >= FS_FAT_SEC_SIZE) {
	  if (j >= FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus) {
		  pFile->CurClust = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, prevclust, 1);
	  }
  }
  FS__fat_free(buffer);
  return ((N * Size - todo) / Size);
}


#endif
#if 0
FS_size_t FS__fat_fread(void *pData, FS_size_t Size, FS_size_t N, FS_FILE *pFile) {
  FS_size_t todo;
  FS_u32 i;
  FS_u32 j;
  FS_u32 fatsize;
  FS_u32 fileclustnum;
  FS_u32 diskclustnum;
  FS_u32 prevclust;
  FS_u32 dstart;
  FS_u32 dsize;
  FS_u32 datastart;
  char *buffer;
  int err;
                                            
  if (!pFile) {
      return 0;  /* No valid pointer to a FS_FILE structure */
  }
  /* Check if media is OK */
  err = FS__lb_status(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo);
  if (err == FS_LBL_MEDIACHANGED) {
    /* Media has changed */
    pFile->error = FS_ERR_DISKCHANGED;
    return 0;
  }
  else if (err < 0) {
    /* Media cannot be accessed */
    pFile->error = FS_ERR_READERROR;
    return 0;
  }
  buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  if (!buffer) {
    return 0;
  }
  fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz16;
  if (fatsize == 0) {
    /* FAT32 */
     fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz32;
  }
  dstart    = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RsvdSecCnt + FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].NumFATs * fatsize;
  dsize     = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RootEntCnt) * FS_FAT_DENTRY_SIZE) / FS_FAT_SEC_SIZE;
  datastart = dstart + dsize;
  prevclust = 0;
  todo = N * Size;
  while (todo) 
  {
	  if (pFile->filepos >= pFile->size) {
		  /* EOF has been reached */
		  pFile->error = FS_ERR_EOF;
		  FS__fat_free(buffer);
		  return ((N * Size - todo) / Size);
	  }
	  fileclustnum = pFile->filepos / (FS_FAT_SEC_SIZE * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus);
	  if (prevclust == 0) {
		  diskclustnum = pFile->CurClust; 
		  if (diskclustnum == 0) {
			  /* Find current cluster by starting at 1st cluster of the file */
			  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pFile->fileid_hi, fileclustnum);
		  }
	  }
	  else {
		  /* Get next cluster of the file */
		  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, prevclust, 1);
	  }
	  prevclust       = diskclustnum;
	  pFile->CurClust = diskclustnum;
	  if (diskclustnum == 0) {
		  /* Could not find current cluster */
		  pFile->error = FS_ERR_READERROR;
		  FS__fat_free(buffer);
		  return ((N * Size - todo) / Size);
	  }
	  diskclustnum -= 2;
	  j = (pFile->filepos % (FS_FAT_SEC_SIZE * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus))/ FS_FAT_SEC_SIZE;

	  while (1) 
	  {
		  if (!todo) {
			  break;  /* Nothing more to write */
		  }
		  if (j >= (FS_u32)FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus) {
			  break;  /* End of the cluster reached */
		  }
		  if (pFile->filepos >= pFile->size) {
			  break;  /* End of the file reached */
		  }
		  err = FS__lb_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
				    datastart +
				    diskclustnum * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus + j,
				    (void*)buffer);
		  if (err < 0) {
			  pFile->error = FS_ERR_READERROR;
			  FS__fat_free(buffer);
			  return ((N * Size - todo) / Size);
		  }
		  i = pFile->filepos % FS_FAT_SEC_SIZE;
		  while (1) 
		  {
			  if (!todo) {
				  break;  /* Nothing more to write */
			  }
			  if (i >= FS_FAT_SEC_SIZE) {
				  break;  /* End of the sector reached */
			  }
			  if (pFile->filepos >= pFile->size) {
				  break;  /* End of the file reached */
			  }
			  *((char*)(((char*)pData) + N * Size - todo)) = buffer[i];
			  i++;
			  pFile->filepos++;
			  todo--;
		  }
		  j++;
	  }  /* Sector loop */
  }  /* Cluster loop */
  if (i >= FS_FAT_SEC_SIZE) {
	  if (j >= FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus) {
		  pFile->CurClust = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, prevclust, 1);
	  }
  }
  FS__fat_free(buffer);
  return ((N * Size - todo) / Size);
}
#endif
typedef struct {

	FS_size_t totalnum;      //total constant sector number
	FS_size_t todo;          //the byte need to read 
	FS_size_t done;          //the byte read done 
	FS_size_t con_flag;      //continue flag 
	FS_size_t preclust;      // previous clust
	FS_size_t i;             // filepos % sector
	FS_size_t j;             // filepos / clustor
	FS_size_t clustsize;     // clust size
	FS_size_t diskclustnum;  // current clust
	FS_size_t saveclustnum;   // save the first sector clust
	FS_size_t secperclust;   // sector per clust
	FS_u32 datastart;        // data start

} FS_READ_INFO;

#if 1
FS_size_t FS__fat_fread_block(void *pData, FS_size_t Size, FS_size_t N, FS_FILE *pFile) {
  FS_size_t todo,done=0;
  FS_u32 i;
  FS_u32 j;
  FS_u32 fatsize;
  FS_u32 fileclustnum;
  FS_u32 diskclustnum;
  FS_u32 prevclust;
  FS_u32 dstart;
  FS_u32 dsize;
  FS_u32 datastart;
  int err,ret;
  FS_u32 clustsize;
  FS_u32 sectornum;
  FS_u32 saveclustnum=0;
  FS_READ_INFO info;
                             
  if (!pFile) {
      return 0;  /* No valid pointer to a FS_FILE structure */
  }
  /* Check if media is OK */
  err = FS__lb_status(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo);
  if (err == FS_LBL_MEDIACHANGED) {
    /* Media has changed */
    pFile->error = FS_ERR_DISKCHANGED;
    return 0;
  }
  else if (err < 0) {
    /* Media cannot be accessed */
    pFile->error = FS_ERR_READERROR;
    return 0;
  }

  fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz16;
  if (fatsize == 0) {
    /* FAT32 */
     fatsize = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].FATSz32;
  }
  dstart    = FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RsvdSecCnt + FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].NumFATs * fatsize;
  dsize     = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].RootEntCnt) * FS_FAT_DENTRY_SIZE) / FS_FAT_SEC_SIZE;
  clustsize = FS_FAT_SEC_SIZE * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus;
  datastart = dstart + dsize;
  prevclust = 0;
  todo = N * Size;
  if(pFile->size-pFile->filepos<todo)
  {
	  todo=pFile->size-pFile->filepos;
  }

  info.totalnum = 0;      
  info.todo=todo;        
  info.done=0;         
  info.con_flag=0;  
  info.clustsize=clustsize; 
  info.datastart=datastart;
  info.saveclustnum=0;   // save the first sector clust
  info.secperclust=FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus;

  while (info.todo) 
  {
	  //printf("todo:%d\n",info.todo);
	  if (pFile->filepos >= pFile->size) {
		  /* EOF has been reached */
		  pFile->error = FS_ERR_EOF;
		  return (done / Size);
	  }
	  fileclustnum = pFile->filepos / clustsize;
	  if (prevclust == 0) {
		  diskclustnum = pFile->CurClust; 
		  if (diskclustnum == 0) {
			  /* Find current cluster by starting at 1st cluster of the file */
			  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pFile->fileid_hi, fileclustnum);
		  }
	  }
	  else {
		  /* Get next cluster of the file */
		  diskclustnum = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, prevclust, 1);
	  }
	  if((diskclustnum-prevclust)==1 || prevclust==0)
	  {
		  info.con_flag=1; 
	  }
	  else
	  {
		  info.con_flag=0;
	  }
	  prevclust       = diskclustnum;
	  pFile->CurClust = diskclustnum;
	  info.preclust=prevclust;
  
	  if (diskclustnum == 0) {
		  /* Could not find current cluster */
		  pFile->error = FS_ERR_READERROR;
		  return (done / Size);
	  }
	  diskclustnum -= 2;
	  info.diskclustnum=diskclustnum;
	  j = (pFile->filepos % clustsize)/ FS_FAT_SEC_SIZE;
	  i = pFile->filepos % FS_FAT_SEC_SIZE;
	  info.i=i;            
	  info.j=j;     
     
	  if(i==0 && j==0 && info.todo >= clustsize)
	  {
		  ret=FS__fat_constant_fread(pData,pFile,&info);
		  if(ret<0)
		  {
			  pFile->error = FS_ERR_READERROR;
			  return (info.done / Size);
		  }
	  }
	  else if(i==0 && j==0 && info.todo < clustsize)
	  {
		  ret=FS__fat_after_fread(pData,pFile,&info);
		  if(ret<0)
		  {
			  pFile->error = FS_ERR_READERROR;
			  return (info.done / Size);
		  }
	  }
	  else
	  {
		  ret=FS__fat_pre_fread(pData,pFile,&info);
		  if(ret<0)
		  {
			  pFile->error = FS_ERR_READERROR;
			  return (info.done / Size);
		  }
	  }
  }
  pFile->error = FS_ERR_EOF;
  
  return (info.done / Size);
}

FS_size_t FS__fat_pre_fread(void *pData, FS_FILE *pFile,FS_READ_INFO *pInfo)
{
	char *buffer;
	int err,i;
	FS_size_t l=0,m=0,len=0;
	FS_size_t sectcnt=0;

	buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
	if (!buffer) {
		return 0;
	}

	l=pInfo->clustsize-(pInfo->j * FS_FAT_SEC_SIZE + pInfo->i);
	m=FS_FAT_SEC_SIZE-pInfo->i;

	if(pInfo->todo < l)
	{
		len=pInfo->todo;
	}
	else
	{
		len=l;
	}
	sectcnt=(pInfo->i+len+FS_FAT_SEC_SIZE-1)/FS_FAT_SEC_SIZE;
	for(i=0;i<sectcnt;i++)
	{
		err = FS__lb_multi_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
					pInfo->datastart + pInfo->diskclustnum *pInfo->secperclust + pInfo->j + i,
					sectcnt,(void*)buffer);
		if (err < 0) {
			pFile->error = FS_ERR_READERROR;
			FS__fat_free(buffer);
			return -1;
		}
		if(i==0 && len <= m)
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done), buffer+ pInfo->i,len);
			pFile->filepos += len;
			pInfo->done += len;
			pInfo->todo -= len;
			len-=len;
		}
		else if(i==0 && len > m)
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done), buffer+ pInfo->i,m);
			pFile->filepos += m;
			pInfo->done += m;
			pInfo->todo -= m;
			len -= m;
		}
		else if(i>0 && len >= FS_FAT_SEC_SIZE)
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done),buffer,FS_FAT_SEC_SIZE);
			pFile->filepos += FS_FAT_SEC_SIZE;
			pInfo->done += FS_FAT_SEC_SIZE;
			pInfo->todo -= FS_FAT_SEC_SIZE;
			len -= FS_FAT_SEC_SIZE;
		}
		else
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done), buffer,len);
			pFile->filepos += len;
			pInfo->done += len;
			pInfo->todo -= len;
			len-=len;
		}
	}
	if((pFile->filepos % pInfo->clustsize)==0)
		pFile->CurClust = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pInfo->preclust, 1);

	pFile->error = FS_ERR_EOF;
	FS__fat_free(buffer);
	return pInfo->done;

}


FS_size_t FS__fat_constant_fread(void *pData,FS_FILE *pFile,FS_READ_INFO *pInfo) 
{
	int err;
	if(pInfo->con_flag)
	{
		pInfo->totalnum +=1;
		pInfo->todo -= pInfo->clustsize;
		pFile->filepos += pInfo->clustsize;
		pFile->CurClust = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pInfo->preclust, 1);
		if(pInfo->totalnum==1)
		{
			pInfo->saveclustnum=pInfo->diskclustnum;
		}

		if(pInfo->todo < pInfo->clustsize)
		{
			if(pInfo->totalnum >0)
			{
				err = FS__lb_multi_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
							pInfo->datastart + pInfo->saveclustnum * FS__FAT_aBPBUnit[pFile->dev_index][pFile->fileid_lo].SecPerClus,(pInfo->totalnum*pInfo->secperclust),	(char *)((unsigned int)pData + pInfo->done));
				
				if (err < 0) {
					pFile->error = FS_ERR_READERROR;
					return -1;
				}
				pInfo->done += pInfo->totalnum*pInfo->clustsize;
				return pInfo->done;
			}
		}
	}
	else
	{
		if(pInfo->totalnum >0)
		{
			err = FS__lb_multi_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
						pInfo->datastart + pInfo->saveclustnum * pInfo->secperclust,
						(pInfo->totalnum*pInfo->secperclust),	(char *)((unsigned int)pData + pInfo->done));
				
			if (err < 0) {
				pFile->error = FS_ERR_READERROR;
				return -1;
			}

			pInfo->done += pInfo->totalnum*pInfo->clustsize;
		}
		pInfo->totalnum=0;
		pInfo->totalnum +=1;
		pInfo->todo -= pInfo->clustsize;
		pFile->filepos += pInfo->clustsize;
		pFile->CurClust = FS__fat_diskclust(pFile->dev_index, pFile->fileid_lo, pInfo->preclust, 1);

		if(pInfo->totalnum==1)
		{
			pInfo->saveclustnum=pInfo->diskclustnum;
		}
		if(pInfo->todo< pInfo->clustsize)
		{
			if(pInfo->totalnum >0)
			{
				err = FS__lb_multi_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
							pInfo->datastart + pInfo->saveclustnum *pInfo->secperclust,
							(pInfo->totalnum * pInfo->secperclust), (char *)((unsigned int)pData + pInfo->done));
				if (err < 0) {
					pFile->error = FS_ERR_READERROR;
					return -1;
				}
				pInfo->done += pInfo->totalnum*pInfo->clustsize;
				return pInfo->done;
			}
		}
	}

}


FS_size_t FS__fat_after_fread(void *pData,FS_FILE *pFile,FS_READ_INFO *pInfo)
{
	char *buffer;
	int err,i;
	FS_size_t l=0;
	FS_size_t sectcnt=0;

	buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
	if (!buffer) {
		return 0;
	}
	sectcnt=(pInfo->todo+FS_FAT_SEC_SIZE-1)/FS_FAT_SEC_SIZE;
	for(i=0;i<sectcnt;i++)
	{

		
		err = FS__lb_multi_read(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo,
					pInfo->datastart + pInfo->diskclustnum * pInfo->secperclust+i,
					1,(void*)buffer);
		if (err < 0) {
			pFile->error = FS_ERR_READERROR;
			FS__fat_free(buffer);
			return -1;
		}
		if(sectcnt-i>1)
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done), buffer,FS_FAT_SEC_SIZE);
			pFile->filepos += FS_FAT_SEC_SIZE ;
			pInfo->done += FS_FAT_SEC_SIZE;
			pInfo->todo -= FS_FAT_SEC_SIZE;
		}
		else
		{
			FS__CLIB_memcpy((char *)((unsigned int)pData + pInfo->done), buffer,pInfo->todo);
			pFile->filepos += pInfo->todo ;
			pInfo->done += pInfo->todo;
			pInfo->todo -= pInfo->todo;
		}
	}
	pFile->error = FS_ERR_EOF;
	FS__fat_free(buffer);
	return pInfo->done;	

}


#endif
